/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package headquarters;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import java.io.Serializable;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jms.Session;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.Table;

import org.hibernate.annotations.Type;
import org.hibernate.ejb.QueryImpl;

/**
 *
 * @author marcin
 */
@Entity
@Table(name = "miasto")
public class City implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "gid")
    private Integer gid;
    @Column(name = "streetlaye")
    private String streetName;
    @Lob
    @Column(name = "the_geom")
    @Type(type = "org.hibernatespatial.GeometryUserType")
    private LineString street;

    public City() {
    }

    public City(Integer gid) {
        this.gid = gid;
    }

    public Integer getGid() {
        return gid;
    }

    public void setGid(Integer gid) {
        this.gid = gid;
    }

    public String getStreetName() {
        return streetName;
    }

    public void setStreetlaye(String streetName) {
        this.streetName = streetName;
    }

    public LineString getStreet() {
        return street;
    }

    public void setStreet(LineString street) {
        this.street = street;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (gid != null ? gid.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof City)) {
            return false;
        }
        City other = (City) object;
        if ((this.gid == null && other.gid != null) || (this.gid != null && !this.gid.equals(other.gid))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "headquarters.City[gid=" + gid + "]";
    }

    public List<City> findAll() {
        EntityManagerFactory emf;
        EntityManager em;
        emf = Persistence.createEntityManagerFactory("PZMDB-app-clientPU");
        em = emf.createEntityManager();
        Query q = em.createQuery("select c from City c");

        org.hibernate.ejb.QueryImpl hs = (QueryImpl) q;

        org.hibernate.Query hbQuery = hs.getHibernateQuery();
//hbQuery.setParameter("dd" ,polygon, org.hibernate.Hibernate.custom(org.hibernatespatial.GeometryUserType.class));


        q.setMaxResults(200);
        List<City> gfs = q.getResultList();
        return gfs;
    }

    public Point randomPoint(int numberStreet, float low, float high, EntityManagerFactory emf) {

        EntityManager em;

        em = emf.createEntityManager();
        GeometryFactory geometryFactory = new GeometryFactory();
        WKTReader reader = new WKTReader(geometryFactory);
        //zwróc część wspólną ulicy i "podulicy", cześć wspólna może być punktem, kawałkiem ulicy, lub też zbiorem pustym
        Query q = em.createQuery("select astext(st_intersection(street,st_line_substring(street,:l,:h))) from City where gid =:g");



        org.hibernate.ejb.QueryImpl hs = (QueryImpl) q;

        org.hibernate.Query hbQuery = hs.getHibernateQuery();
        hbQuery.setParameter("l", low);
        hbQuery.setParameter("h", high);
        hbQuery.setParameter("g", numberStreet);

        q.setMaxResults(200);
        List<String> gfs = q.getResultList();
        if (gfs.isEmpty()) {
            
            hbQuery.setParameter("l", 0);
            hbQuery.setParameter("h", 1);
            hbQuery.setParameter("g", numberStreet);
            gfs = q.getResultList();
        }

        try {
            Geometry g = (Geometry) reader.read(gfs.get(0));


            if (g instanceof Point) {
               
                return (Point) g;
            } else if (g instanceof MultiLineString) {
                
                MultiLineString tmp = (MultiLineString) g;
                LineString ls = (LineString) tmp.getGeometryN(0);
                return ls.getStartPoint();

            } else {
                LineString ls = (LineString) g;
               
                return ls.getStartPoint();
            }


        } catch (ParseException ex) {

            Logger.getLogger(City.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }

//      
    }

    public static void main(String[] args) {
        Random rand = new Random();
        int numberStreet = rand.nextInt(6);
        EntityManagerFactory emf;
        EntityManager em;

        emf = Persistence.createEntityManagerFactory("PZMDB-app-clientPU");
        em = emf.createEntityManager();

        Query q = em.createQuery("select c from City c");
        List list = q.getResultList();
//        Float x;
//        Float l;
//        Float h;
//        while (true) {
//            x = rand.nextFloat();
//            l = x;
//            if (l > 0.5) {
//                h = new Float(1);
//            } else {
//                h = new Float(l + 0.5);
//            }
//            new City().randomPoint(numberStreet, l, h, emf);
//        }

    }
}
